package com.sparrow.mvc.ui;

import java.sql.ResultSet;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;
import com.sparrow.constant.CONFIG;
import com.sparrow.core.Log;
import com.sparrow.orm.DBHelper;
import com.sparrow.utils.Config;
import com.sparrow.utils.HtmlUtil;
import com.sparrow.utils.StringUtil;

/**
 * 数据网格控件
 * 
 * @author zhanglizhi
 * @date Apr 9, 2011 10:50:46 PM
 * @version 1.0
 */
@SuppressWarnings("serial")
public class JGridView extends JWebControl {

	private String emptyString = "没有符合条件的记录。";
	/**
	 * tab缩进数
	 */
	private String indent = "3";
	/**
	 * title1,2(colSpan)|title2|...
	 */
	private String headTitles;
	/**
	 * 表头HTML
	 */
	private String headTitleHtml;
	/**
	 * 字段的拼写分为三类 html 则为html字符串 static则为静态字段 dynamic则为动态字段由IJGridView接口中定义方法。
	 * 字符串举例
	 * static#textFiledName#text#textfieldTextLength#textDefaultValue$width
	 * (px)$align|
	 * html#htmlText:+static#imageFiledName#image#width#height$width(px)$align|
	 * static#hyperFiledName#hyper#urlPrefix#forumId#textLength$width(px)$align|
	 * static#fieldName&fieldName2#button#value#javascriptClickEvent(parameter1,
	 * parameter2)#cssClass dynamic#field1#field2....
	 */
	private String fields;

	/**
	 * 当前页码
	 */
	private int currentPageIndex = 1;
	/**
	 * 每页记录数
	 */
	private int pageSize = 10;
	/**
	 * 记录总数
	 */
	private int recordCount = 0;
	/**
	 * 是否显示页码
	 */
	private boolean showPage = true;
	/**
	 * 是否显示列头
	 */
	private boolean showHead = true;
	/**
	 * 是否显示空行
	 */
	private boolean showEmptyRow;
	/**
	 * gridView接口对象为绑定数据提供
	 */
	private DynamicRow gridView;
	/**
	 * 分页链接字符格式
	 */
	private String pageFormat;
	/**
	 * 是否使用鼠标悬停事件
	 */
	private boolean useMouseEvent = true;
	/**
	 * 是否使用隔行不同样式
	 */
	private boolean useAlternatingRowStyle = true;

	/**
	 * 数据绑定委托
	 * 
	 * @author zhanglizhi
	 * @date Apr 9, 2011
	 * @version 1.0
	 * @return
	 */
	public DynamicRow getGridView() {
		Object gridHandle = super.pageContext.getRequest().getAttribute(
				this.getId() + ".gridView");
		if (gridHandle == null) {
			gridHandle = this.gridView;
		}
		return (DynamicRow) gridHandle;
	}

	/**
	 * 获取ResultSet
	 * 
	 * @author zhanglizhi
	 * @date Apr 9, 2011
	 * @version 1.0
	 * @return
	 */
	public ResultSet getRs() {
		Object ors = super.pageContext.getRequest().getAttribute(
				this.getId() + ".dataSource");
		if (ors != null)
			return (ResultSet) ors;
		else
			return null;
	}

	@Override
	public int doStartTag() throws JspException {
		int returnValue = TagSupport.SKIP_BODY;
		if (this.getVisible().toLowerCase() != "false") {
			StringBuffer writeHTML = new StringBuffer();
			writeHTML.append("<table cellpadding=\"4\" cellspacing=\"0\"");
			writeHTML.append(String.format(" id=\"%1$s\"", this.getId()));
			writeHTML.append(this.getCssClass());
			writeHTML.append(this.getCssText());
			writeHTML.append(this.getTitle());
			writeHTML.append(this.getEvents());
			writeHTML.append(">");
			writeHTML.append("<tbody>");
			if (this.isShowHead()) {
				if (!StringUtil.isNullOrEmpty(this.getHeadTitleHtml())) {
					writeHTML.append(this.getHeadTitleHtml());
				} else {
					writeHTML
							.append(StringUtil.getIndent(this.getIndentCount() + 1)
									+ "<tr class=\"headRow\">");
					// title1$colSpan|title2|...
					String[] headTitle = this.getHeadTitles().split("\\|");
					for (int i = 0; i < headTitle.length; i++) {
						if (headTitle[i].equals("checkBox")) {
							writeHTML
									.append(StringUtil.getIndent(this
											.getIndentCount() + 2)
											+ "<th style=\"text-align:center;\">"
											+ StringUtil.getIndent(this
													.getIndentCount() + 3)
											+ "<input id=\""
											+ this.getId()
											+ "_checkall\" onclick=\"gridView.allCheckClick(this);\" type=\"checkbox\"/>"
											+ StringUtil.getIndent(this
													.getIndentCount() + 2)
											+ "</th>");
						} else {
							writeHTML
									.append(headTitle[i].contains("$") ? String.format(
											StringUtil.getIndent(this
													.getIndentCount() + 2)
													+ "<th style=\"text-align:center;\" colspan=\"%2$s\">%1$s</th>",
											headTitle[i].split("\\$")[0],
											headTitle[i].split("\\$")[1])
											: String.format(
													StringUtil
															.getIndent(this
																	.getIndentCount() + 2)
															+ "<th style=\"text-align:center;\">%1$s</th>",
													headTitle[i]));
						}
					}
					writeHTML
							.append(StringUtil.getIndent(this.getIndentCount() + 1)
									+ "</tr>");
				}
			}
			try {
				if (this.getRs() != null) {
					this.getRs().beforeFirst();
					this.recordCount = 0;
					String[] filed = this.getFields().split("\\|");
					// filedInfo[0]带有属性的字段信息 filedInfo[1]宽度:px
					// filedInfo[2]:align对齐方式
					String[][] filedInfo = new String[filed.length][3];
					for (int i = 0; i < filed.length; i++) {
						if (filed[i].contains("$")) {
							filedInfo[i] = filed[i].split("\\$");
						} else {
							filedInfo[i][0] = filed[i];
						}
					}

					while (this.getRs().next()) {
						String mouseoverEvent = this.isUseMouseEvent() == true ? " onmouseover=\"mouse.over(this);\"  onmouseout=\"mouse.out(this);\""
								: "";
						String alternatingRowStyle = this
								.isUseAlternatingRowStyle() == true ? " style='background:white;'"
								: "";
						if (this.recordCount % 2 == 0) {
							writeHTML.append(StringUtil.getIndent(this
									.getIndentCount() + 1)
									+ "<tr class=\"dataRow\" "
									+ mouseoverEvent
									+ alternatingRowStyle + ">");
						} else {
							writeHTML.append(StringUtil.getIndent(this
									.getIndentCount() + 1)
									+ "<tr class=\"dataRow\" "
									+ mouseoverEvent
									+ alternatingRowStyle + ">");
						}
						for (int i = 0; i < filed.length; i++) {
							writeHTML
									.append(String.format(
											StringUtil.getIndent(this
													.getIndentCount() + 2)
													+ "<td %2$s align=\"%3$s\">%1$s"
													+ StringUtil.getIndent(this
															.getIndentCount() + 2)
													+ "</td>",
											this.getTDinnerHTML(filedInfo[i][0]
													.trim()),
											// 如果width不为null则设置TD宽度
											filedInfo[i][1] == null ? ""
													: "style=\"width:"
															+ filedInfo[i][1]
																	.trim()
															+ "\"",
											// 如果align不为null则设置TD的align为left
											filedInfo[i][2] == null ? "left"
													: filedInfo[i][2].trim()

									));
						}
						writeHTML.append(StringUtil.getIndent(this
								.getIndentCount() + 1) + "</tr>");
					}
					if (this.recordCount == 0 && this.isShowEmptyRow()) {
						writeHTML.append("<tr><td>" + this.getEmptyString()
								+ "<td></tr>");
					}
					if (this.isShowPage()) {
						writeHTML.append(String.format(
								StringUtil.getIndent(this.getIndentCount() + 1)
										+ "<tr>"
										+ StringUtil.getIndent(this
												.getIndentCount() + 2)
										+ "<td colspan=%1$s>%2$s"
										+ StringUtil.getIndent(this
												.getIndentCount() + 2)
										+ "</td>"
										+ StringUtil.getIndent(this
												.getIndentCount() + 1)
										+ "</tr>", filed.length, HtmlUtil
										.getPageString(
												this.getCurrentPageIndex(),
												this.getRecordCount(),
												this.getPageSize(),
												this.getPageFormat())));
					}

				}
				writeHTML.append(StringUtil.getIndent(this.getIndentCount())
						+ "</tbody></table>");
				JspWriter out = this.pageContext.getOut();
				out.print(writeHTML.toString());
			} catch (Exception e1) {
				Log.getInstance().error(e1);
			}
			if (this.getRs() != null) {
				DBHelper.getInstance().release(this.getRs());
			}
		}
		return returnValue;
	}

	public String getEmptyString() {
		return emptyString;
	}

	public void setEmptyString(String emptyString) {
		this.emptyString = emptyString;
	}

	public String getHeadTitles() {
		Object requestHeadTitles = this.pageContext.getRequest().getAttribute(
				this.getId() + ".headTitles");
		if (requestHeadTitles != null) {
			this.headTitles = requestHeadTitles.toString();
		} else if (this.headTitles == null) {
			Log.getInstance().warm("请定义headTitles属性");
		}
		return this.headTitles;
	}

	public void setHeadTitles(String headTitles) {

		this.headTitles = headTitles;
	}

	public String getFields() {
		Object requestFields = this.pageContext.getRequest().getAttribute(
				this.getId() + ".fields");
		if (requestFields != null) {
			this.fields = requestFields.toString();
		}
		return this.fields;
	}

	public void setFields(String fields) {
		this.fields = fields;
	}

	public int getRecordCount() {
		Object recordCount = super.pageContext.getRequest().getAttribute(
				this.getId() + ".recordCount");
		if (recordCount != null) {
			this.recordCount = Integer.valueOf(recordCount.toString());
		}
		return this.recordCount;
	}

	public int getPageSize() {
		Object requestPageSize = this.pageContext.getRequest().getAttribute(
				this.getId() + ".pageSize");
		if (requestPageSize != null) {
			this.pageSize = Integer.valueOf(requestPageSize.toString());
		}
		return this.pageSize;
	}

	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	/**
	 * 获取当前页码
	 * 
	 * @author zhanglizhi
	 * @date Apr 9, 2011
	 * @version 1.0
	 * @return
	 */
	public int getCurrentPageIndex() {
		int pageIndex = this.currentPageIndex;
		Object ocurrentPageIndex = this.pageContext.getRequest().getParameter(
				"currentPageIndex");
		if (ocurrentPageIndex != null) {
			pageIndex = Integer.valueOf(ocurrentPageIndex.toString());
		}
		return pageIndex;
	}

	/**
	 * 获取单元格数据 字段例如: static#fieldName#text+html#/+static#fieldName2#text
	 * dynamic#fieldName1#filedName2..... html#htmlText
	 * 
	 * @author zhanglizhi
	 * @date Apr 9, 2011
	 * @version 1.0
	 * @param tdInfo
	 * @return
	 * @throws Exception
	 */
	private String getTDinnerHTML(String tdInfo) throws Exception {
		// static#fieldName#text+html#/+static#fieldName2#text
		String[] filedInfo = tdInfo.split("\\+");
		StringBuffer htmlLabel = new StringBuffer();
		for (int i = 0; i < filedInfo.length; i++) {
			// static#fieldName#text...
			String[] fieldAttribute = filedInfo[i].split("\\#");
			if (filedInfo[i].startsWith("html")) {
				// html#/br
				htmlLabel
						.append(StringUtil.getIndent(this.getIndentCount() + 3)
								+ fieldAttribute[1].replace("br", "<br/>"));
			} else if (filedInfo[i].startsWith("dynamic")) {
				// dynamic#filedName#def1#def2
				if (this.getGridView() == null) {
					Log.getInstance().warm("请定义IDynamicRow接口引用");
				} else {
					try {
						htmlLabel.append(this.getGridView().bindRowInfo(
								fieldAttribute, this.getRs()));
					} catch (Exception e) {
						Log.getInstance().error(e);
					}
				}
			} else if (filedInfo[i].startsWith("static")) {
				String fieldValue = null;
				// 字段信息不包含&则表示是字段信息，预先取值。
				if (fieldAttribute[1].indexOf('&') == -1) {
					fieldValue = this.getRs().getString(
							fieldAttribute[1].trim());
				}
				// static#textFiledName
				// static#textFiledName#text#textfieldTextLength#textDefaultValue
				if (fieldAttribute.length == 2
						|| fieldAttribute[2].trim().equals("text")) {
					// 如果fieldValue值为""并且默认值不为空则将默认值赋给fieldValue
					if (StringUtil.isNullOrEmpty(fieldValue)) {
						if (fieldAttribute.length == 5) {
							fieldValue = fieldAttribute[4];
						} else {
							fieldValue = "-";
						}
					}
					// static#textFieldName
					// static#textFiledName#text
					// static#textFiledName#text.-1
					if (fieldAttribute.length == 2
							|| fieldAttribute.length == 3
							|| (fieldAttribute.length > 3 && fieldAttribute[3]
									.equals("-1"))) {
						htmlLabel.append(StringUtil.getIndent(this
								.getIndentCount() + 3) + fieldValue);

					} else {
						htmlLabel
								.append(String.format(
										StringUtil.getIndent(this
												.getIndentCount() + 3)
												+ "<span style=\"width:%2$spx;line-height:18px;height:20px;display:block;overflow:hidden;\"  class=\"class_%3$s\" title=\"%1$s\">%1$s</span>",
										fieldValue, fieldAttribute[3],
										fieldAttribute[1]));
					}

				} else if (fieldAttribute[2].trim().equals("image")) {
					// static#imageFiled#image#60px#40px#defaultIco
					String ico = fieldValue;
					if (StringUtil.isNullOrEmpty(fieldValue)) {
						ico = Config.getValueInCache(CONFIG.RESOURCE)
								+ fieldAttribute[5];
					}
					htmlLabel
							.append(String.format(
									StringUtil
											.getIndent(this.getIndentCount() + 3)
											+ "<img src=\"%1$s\" style=\"width:%2$s;height:%3$s\"/>",
									ico, fieldAttribute[3], fieldAttribute[4]));
				} else if (fieldAttribute[2].trim().equals("hyper")) {
					// static#hyperFiledName#hyper#target#urlPrefix.html#idField#textLength
					String idField = this.getRs().getString(fieldAttribute[5]);
					if (idField == null) {
						idField = "-";
					}
					String hyperLink = fieldAttribute[4]
							.replace("{0}", idField);
					htmlLabel
							.append(String
									.format("<a title=\"%3$s\" target=\"%5$s\" href=\"%1$s%2$s\">%4$s</a>",
											hyperLink.startsWith("/http://") ? ""
													: Config.getValueInCache(CONFIG.ROOT_PATH),
											hyperLink.startsWith("/http://") ? hyperLink
													.substring(1) : hyperLink,
											fieldValue,
											StringUtil.subStringByByte(
													fieldValue,
													Integer.valueOf(fieldAttribute[6])),
											fieldAttribute[3]));

				} else if (fieldAttribute[2].trim().equals("imageButton")) {
					// htmlLabel="<input type=\"img\" ";
				} else if (fieldAttribute[2].trim().equals("button")) {
					// static#fieldName&fieldName2#button#value#javascriptClickEvent(parameter1,parameter2)#cssClass
					String[] fieldNameArray = fieldAttribute[1].split("&");
					String clientHandle = fieldAttribute[4];
					for (int index = 0; index < fieldNameArray.length; index++) {
						fieldValue = this.getRs().getString(
								fieldNameArray[index]);
						clientHandle = clientHandle.replace("{" + index + "}",
								fieldValue == null ? "" : fieldValue);
					}
					String strClass = "";
					if (fieldAttribute.length == 6) {
						strClass = String.format("class=\"%1$s\"",
								fieldAttribute[5]);
					}
					htmlLabel
							.append(String
									.format("<input type=\"button\" value=\"%1$s\" onclick=\"%2$s\" %3$s/>",
											fieldAttribute[3], clientHandle,
											strClass));
				} else if (fieldAttribute[2].trim().equals("checkBox")) {

					htmlLabel.append("<input id=\"" + fieldValue
							+ "\" onclick=\"gridView.recordCheckClick(this,'"
							+ this.getId()
							+ "_checkall');\" type=\"checkbox\" name=\""
							+ this.getId() + "\"/>");
				}
			}
		}
		return htmlLabel.toString();
	}

	public Boolean isShowPage() {
		return showPage;
	}

	public void setShowPage(Boolean showPage) {
		this.showPage = showPage;
	}

	public int getIndentCount() {
		return Integer.valueOf(this.indent);
	}

	public String getIndent() {
		return this.indent;
	}

	public void setIndent(String indent) {
		this.indent = indent;

	}

	public String getPageFormat() {
		Object requestPageFormat = this.pageContext.getRequest().getAttribute(
				this.getId() + ".pageFormat");
		if (requestPageFormat != null) {
			this.pageFormat = requestPageFormat.toString();
		} else if (this.pageFormat != null
				&& !this.pageFormat.trim().equals("")) {
			this.pageFormat = this.pageFormat.replace("$rootPath",
					Config.getValueInCache(CONFIG.ROOT_PATH));
		}

		return this.pageFormat;
	}

	public void setPageFormat(String pageFormat) {
		this.pageFormat = pageFormat;
	}

	public boolean isUseMouseEvent() {
		return useMouseEvent;
	}

	public void setUseMouseEvent(boolean useMouseEvent) {
		this.useMouseEvent = useMouseEvent;
	}

	public boolean isUseAlternatingRowStyle() {
		return useAlternatingRowStyle;
	}

	public void setUseAlternatingRowStyle(boolean useAlternatingRowStyle) {
		this.useAlternatingRowStyle = useAlternatingRowStyle;
	}

	public boolean isShowHead() {
		return showHead;
	}

	public void setShowHead(boolean showHead) {
		this.showHead = showHead;
	}

	public boolean isShowEmptyRow() {
		return showEmptyRow;
	}

	public void setShowEmptyRow(boolean showEmptyRow) {
		this.showEmptyRow = showEmptyRow;
	}

	public String getHeadTitleHtml() {
		return headTitleHtml;
	}

	public void setHeadTitleHtml(String headTitleHtml) {
		this.headTitleHtml = headTitleHtml;
	}

}
